
#include "EventLoop.hpp"
#include "Channel.hpp"
#include <sys/epoll.h>

namespace zephyr {

const int Channel::k_NoneEvent = 0;
const int Channel::k_ReadEvent = EPOLLIN | EPOLLPRI;
const int Channel::k_WriteEvent = EPOLLOUT;

Channel::Channel(EventLoop *loop, int fd)
    : m_loop(loop)
    , m_fd(fd)
    , m_events(k_NoneEvent)
    , m_revents(0)
    , m_index(-1)
    , m_tied(false) {}
Channel::~Channel() {}

void Channel::tie(const std::shared_ptr<void> &obj) {
    m_tie = obj;
    m_tied = true;
}

// channel fd所关心的事件发生变化后 调用update更新polller中的状态
void Channel::update() {
    // 通过channel所属的eventloop，调用poller的相应方法，注册fd的events事件
    m_loop->updateChannel(this);
}

void Channel::remove() {
    m_loop->removeChannel(this);
}

void Channel::handleEvent(Timestamp recviveTime) {
    if (m_tied) {
        std::shared_ptr<void> guard = m_tie.lock();
        if (guard) {
            handleEventWithGuard(recviveTime);
        }
    } else {
        handleEventWithGuard(recviveTime);
    }
}

void Channel::handleEventWithGuard(Timestamp recviveTime) {
    if ((m_revents & EPOLLHUP) && !(m_revents & EPOLLIN))
        if (m_closeCallback)
            m_closeCallback();

    if (m_revents & EPOLLERR)
        if (m_errorCallback)
            m_errorCallback();

    if (m_revents & (EPOLLIN | EPOLLPRI))
        if (m_readCallback)
            m_readCallback(recviveTime);

    if (m_revents & EPOLLOUT)
        if (m_writeCallback)
            m_writeCallback();
}

}